local GetCollision: (Origin:Vector3, Direction:Vector3) -> (Vector3, Color3) local LightPos = Vector3.new(0, 5, 0) do --Shader --Params local MaxDistance = 10 local MinDistance = .03 local ConePosition = Vector3.new(1.5, 2., 7.5) local ConeRot = CFrame.fromEulerAnglesYXZ(0, 0, 0) local ConeSize = Vector3.new(1.5, 2.5, 1.5) local TrunkHeight = 4 local TrunkSize = Vector3.new(1.5, 7, 1.5) local LightDistance = 60 local PebbleSize = Vector3.new(2, 1, 2) local PebbleRadius = .025 local Hash33: (Vector3) -> Vector3 local Hash23: (Vector2) -> Vector3 local Hash22: (Vector2) -> Vector2 local Hash21: (Vector2) -> number do --Hash functions local Hash33A = Vector3.new(67.47834, 52.5363, 67.4353) local Hash33B = Vector3.new(84.25652, 76.4533, 34.5474) local Hash33C = Vector3.new(32.63437, 56.7483, 87.2445) function Hash33(Point:Vector3):Vector3 return Vector3.new( (math.cos(Point:Dot(Hash33A)) * 45363.46356) % 1, (math.cos(Point:Dot(Hash33B)) * 34364.57434) % 1, (math.cos(Point:Dot(Hash33C)) * 67343.64473) % 1 ) end local Hash23A = Vector2.new(67.47834, 52.5363) local Hash23B = Vector2.new(84.25652, 34.5474) local Hash23C = Vector2.new(56.74834, 87.2445) function Hash23(Point:Vector2):Vector3 return Vector3.new( (math.cos(Point:Dot(Hash23A)) * 35637.46356) % 1, (math.cos(Point:Dot(Hash23B)) * 15663.57434) % 1, (math.cos(Point:Dot(Hash23C)) * 13633.64473) % 1 ) end function Hash22(Point:Vector2):Vector2 return Vector2.new( (math.cos(Point:Dot(Hash23B)) * 15663.57434) % 1, (math.cos(Point:Dot(Hash23C)) * 13633.64473) % 1 ) end function Hash21(Point:Vector2):number return (math.cos(Point:Dot(Hash23A)) * 64671.76782) % 1 end end --Common local Vec3d5 = Vector3.one * .5 --SDFs local function GroundSDF(Point:Vector3):number return Point.Y; end local ConeShift = Vector3.new(.9, .2, .9) local ConeSizeOffset = ConeSize * Vector3.new(1., 2., 1.) local function ConeSDF(Point:Vector3):number local Temp = Point / 2 / ConeSize Point = Point - (ConePosition + (Hash33(Vector3.new(math.floor(Temp.X), math.floor(Temp.Y), math.floor(Temp.Z))) - Vec3d5) * ConeShift) Point = Point / ConeSizeOffset Point = Vector3.new((Point.X + 1.) % 2 - 1., Point.Y - .25, (Point.Z + 1.) % 2 - 1.) Point = ConeRot * Point return math.max(Point.Magnitude - 1.392 * -Point.Y, (Point - Vector3.new(math.clamp(Point.X, -.5, .5), math.clamp(Point.Y, -.5, .5), math.clamp(Point.Z, -.5, .5))).Magnitude) end local TrunkPosition = ConePosition - Vector3.yAxis * TrunkHeight local TrunkShift = Vector3.new(1, .2, 1) local TrunkSizeOffset = TrunkSize * Vector3.new(1., 2., 1.) local function TrunkSDF(Point:Vector3):number local Temp = Point / 2 / ConeSize Point = Point - (TrunkPosition + (Hash33(Vector3.new(math.floor(Temp.X), math.floor(Temp.Y), math.floor(Temp.Z))) - Vec3d5) * TrunkShift) Point = Point / TrunkSizeOffset Point = Vector3.new((Point.X + 1.) % 2 - 1., Point.Y - .25, (Point.Z + 1.) % 2 - 1.) Point = ConeRot * Point return math.max(Point.Magnitude - 1.392 * -Point.Y, (Point - Vector3.new(math.clamp(Point.X, -.5, .5), math.clamp(Point.Y, -.5, .5), math.clamp(Point.Z, -.5, .5))).Magnitude) end local function PebbleSDF(Point:Vector3):number local Temp = Point / PebbleSize / .25 + Vec3d5 local Hash = Hash33(Vector3.new(math.floor(Temp.X), math.floor(Temp.Y), math.floor(Temp.Z))) - Vec3d5 Point = Point - Vector3.new(Hash.X * .37, -(Hash.Y * Hash.Y) * 1.5, Hash.Z * .37) Point = Point / PebbleSize Point = Vector3.new((Point.X + .125) % .25 - .125, Point.Y, (Point.Z + .125) % .25 - .125) return Point.Magnitude - PebbleRadius end --Normals local function GroundNormal(Hit:Vector3):Vector3 local Offset = Hash22(Vector2.new(math.floor(Hit.X * 50) * .02, math.floor(Hit.Z * 50) * .02)) return Vector3.new(Offset.X * .3 - .15, 1, Offset.Y * .3 - .15).Unit end local ConeTip = ConeSize * Vector3.yAxis local function ConeNormal(Hit:Vector3):Vector3 local Temp = Hit / 2 / ConeSize Hit = Hit - (ConePosition + (Hash33(Vector3.new(math.floor(Temp.X), math.floor(Temp.Y), math.floor(Temp.Z))) - Vec3d5) * ConeShift) Hit = Hit / ConeSizeOffset Hit = Vector3.new((Hit.X + 1.) % 2 - 1., Hit.Y - .25, (Hit.Z + 1.) % 2 - 1.) Hit = ConeRot * Hit local uv = ConeRot * (Hit * .6) return (ConeRot:Inverse() * CFrame.lookAt(Hit, ConeTip).UpVector + Hash23(Vector2.new(uv.X, uv.Y)) * .8 - Vector3.one * .4).Unit end local TrunkTip = TrunkSize * Vector3.yAxis local function TrunkNormal(Hit:Vector3):Vector3 local Temp = Hit / 2 / ConeSize Hit = Hit - (TrunkPosition + (Hash33(Vector3.new(math.floor(Temp.X), math.floor(Temp.Y), math.floor(Temp.Z))) - Vec3d5) * TrunkShift) Hit = Hit / TrunkSizeOffset Hit = Vector3.new((Hit.X + 1.) % 2 - 1., Hit.Y - .25, (Hit.Z + 1.) % 2 - 1.) Hit = ConeRot * Hit return ConeRot:Inverse() * CFrame.lookAt(Hit, TrunkTip).UpVector end local function PebbleNormal(Hit:Vector3):Vector3 local Temp = Hit / PebbleSize / .25 + Vec3d5 local Hash = Hash33(Vector3.new(math.floor(Temp.X), math.floor(Temp.Y), math.floor(Temp.Z))) - Vec3d5 Hit = Hit - Vector3.new(Hash.X * .37, -(Hash.Y * Hash.Y) * 1.5, Hash.Z * .37) Hit = Hit / PebbleSize Hit = Vector3.new((Hit.X + .125) % .25 - .125, Hit.Y, (Hit.Z + .125) % .25 - .125) return Hit.Unit end --March local function GetDistance(Position:Vector3):number return math.min(GroundSDF(Position), ConeSDF(Position), TrunkSDF(Position), PebbleSDF(Position)) end local function March(RayOrigin:Vector3, RayDirection:Vector3, MaxDistance):number local Distance = GetDistance(RayOrigin) while true do local Delta = GetDistance(RayOrigin + RayDirection * Distance) Distance = Distance + Delta if Delta < MinDistance or Distance > MaxDistance then break end end return math.clamp(Distance, 0, MaxDistance) end --Material local GroundColor = Vector3.new(.6, .8, .4) local ConeColor = Vector3.new(.7, .8, .4) local TrunkColor = Vector3.new(.4, .25, .1) local function ApplyMaterial(Hit:Vector3, Direction:Vector3):Color3 local BaseColor = Vector3.zero local Distance = GetDistance(Hit) local Length = (LightPos - Hit).Magnitude local Light = math.clamp((LightDistance - Length) / LightDistance, 0, 1) Direction = (LightPos - Hit).Unit local Shadow = March(Hit + Direction * .1, Direction, Length) / Length if GroundSDF(Hit) == Distance then BaseColor = Vector3.one * (((math.floor(Hit.X + Hash21(Vector2.new(Hit.X, Hit.Z)) * .1) + math.floor(Hit.Z + Hash21(Vector2.new(Hit.Z, Hit.X)) * .1)) % 2) * .3 + .7) BaseColor = BaseColor * Shadow * math.clamp(GroundNormal(Hit):Dot(Direction), 0, 1) * Light BaseColor = BaseColor * GroundColor elseif ConeSDF(Hit) == Distance then local Normal = ConeNormal(Hit) local Temp = Hit / 2 / ConeSize BaseColor = ConeColor * (Normal:Dot(Direction) * Light * Shadow) * (Hash33(Vector3.new(math.floor(Temp.X), math.floor(Temp.Y), math.floor(Temp.Z))) * .3 + Vector3.one * .7) elseif TrunkSDF(Hit) == Distance then local Normal = TrunkNormal(Hit) local uv = Vector2.new(math.floor(Normal.X * 20) * .05 + Hit.X * .3, math.floor(Normal.Z * 20) * .05 + Hit.Z * .3) local Temp = Hit / 2 / ConeSize BaseColor = TrunkColor * Hash21(uv) * (Normal:Dot(Direction) * Light * Shadow) * (Hash33(Vector3.new(math.floor(Temp.X), math.floor(Temp.Y), math.floor(Temp.Z))) * .3 + Vector3.one * .7) elseif PebbleSDF(Hit) == Distance then local Hash = Hash33(Vector3.new(math.floor(Hit.X), math.floor(Hit.Y), math.floor(Hit.Z))) BaseColor = ((Vector3.one * Hash.X) * .5 + Vector3.one * .4) * (Vector3.one * Hash21(Vector2.new(math.floor(Hit.X * 300) * .0015, math.floor(Hit.Z * 300) * .0015)) * PebbleNormal(Hit):Dot(Direction) * Shadow * .8 + Vector3.one * .2) * Light end return Color3.new(math.clamp(BaseColor.X, 0, 1), math.clamp(BaseColor.Y, 0, 1), math.clamp(BaseColor.Z, 0, 1)) end --Draw function GetCollision(Origin:Vector3, Direction:Vector3): (Vector3, Color3) Origin = Origin * .1 local Depth = March(Origin, Direction, MaxDistance) if Depth ~= MaxDistance then local Hit = Origin + Direction * Depth return Hit * 10, ApplyMaterial(Hit, Direction) end end end do --Tools do --LightTool local Tool = Instance.new("Tool") Tool.Name = "MoveLight" local Handle = Instance.new("Part", Tool) Handle.Material = Enum.Material.Neon Handle.Size = Vector3.one Handle.Color = Color3.new(1, 0.811765, 0.129412) Handle.Name = "Handle" Tool.Parent = owner.Backpack local function OnActivation() for i, v in ipairs(script:GetChildren()) do v:Destroy() if i % 100 == 0 then task.wait() end end LightPos = Handle.Position * .1 end Tool.Activated:Connect(OnActivation) end do --Cast tool local Tool = Instance.new("Tool") Tool.Name = "CastRay" local Handle = Instance.new("Part", Tool) Handle.Size = Vector3.one Handle.Name = "Handle" Tool.Parent = owner.Backpack local RefPart = Instance.new("WedgePart") RefPart.Anchored = true RefPart.CanQuery = false RefPart.CanTouch = false RefPart.Size = Vector3.one * .5 local Mesh = Instance.new("SpecialMesh", RefPart) Mesh.MeshType = Enum.MeshType.Sphere Mesh.Scale = Vector3.one * .5 local Cast = Instance.new("RemoteEvent") Cast.Name = "Cast" Cast.Parent = Tool local function OnCast(Who:Player, Towards:Vector3):nil for Y = -3, 3 do for X = -3, 3 do local Offset = CFrame.lookAt(Handle.Position, Towards) Offset = (Offset - Offset.Position) * Vector3.new(X * .1, Y * .1, -1) + Vector3.new(math.random() - .5, math.random() - .5, math.random() - .5) * .2 local Hit, Color = GetCollision(Handle.Position, Offset.Unit) if Hit then local Clone = RefPart:Clone() Clone.Position = Hit Clone.Color = Color Clone.Parent = script end end end end Cast.OnServerEvent:Connect(OnCast) NLS([[ local Tool = script.Parent local Mouse = owner:GetMouse() local Cast = Tool.Cast local function OnActivation() Cast:FireServer(Mouse.Hit.Position) end Tool.Activated:Connect(OnActivation) --]], Tool) end end